package ANALISIS;

import VISTA.Frm_AnalizadorLexico;
import java.util.Hashtable;
import java.util.StringTokenizer;


/*
 * @author ESTUDIANTES DE SISTEMAS DE LA UNIVERSIDAD SAN LUIS GONZAGA DE ICA
 */
public class AnalizadorLexico {

    public String resultado = ""; // SE MOSTRARÁ EN EL AREA DE TEXTO DEL RESULTADO DE LA VISTA
    public String varPalabReserv = "";
    public String varTipoDato = null;
    public String varNombreVar = "";
    public int contadortipodato = 0;
    public String mensajeSintactico = ">>>>>>>>>>>>>>>>>>>>>>RESULTADO DE ERRORES<<<<<<<<<<<<<<<<<";
    /*
     PROBANDO LA MATRIZ DE ESTADOS
     */
    public String[][] array = new String[1000][2];
    public int[][] misEstados = {{1, -4, 4, -4}, {1, 2, -1, -1}, {3, -2, -2, -2}, {3, -2, -2, -2}, {4, -3, 4, -3}}; // REPRESENTA EL "ESTADO" EN LA TABLA DE AUTOMATAS
    int cod_entrada; // REPRESENTA LA "ENTRADA" EN LA TABLA DE AUTOMATAS

    public AnalizadorLexico(String f) {
        StringTokenizer tokenlinea = new StringTokenizer(f, "\n");
        StringTokenizer tokenespacio;
        String[] orden = new String[3];
        while (tokenlinea.hasMoreTokens()) {//separa texto en lineas

            tokenespacio = new StringTokenizer(tokenlinea.nextToken());

            while (tokenespacio.hasMoreTokens()) { //separa lineas en palabras

                String cad = tokenespacio.nextToken();//eliminamos los espacios en blanco al inicio o al final (pero no a la mitad)
                int longitud_cad = cad.length();

                int i = 0; // PARA GUARDAR POSICION DE CARACTER
                String concat = ""; // PARA CONCATENAR CADA CARACTER
                int estado = 0; // EN CADA TOKEN DE ESPACIO EL ESTADO REGRESA A CERO


                while (i < longitud_cad) {

                    char t = cad.charAt(i);//vamos leyendo caracter por caracter

                    if (evaluarOperadorRelacional(String.valueOf(t)) != null || evaluarDelimitador(String.valueOf(t)) != null || evaluarOperadorAritmetico(String.valueOf(t)) != null || t == ' ') {
                        if (evaluarOperadorRelacional(String.valueOf(t)) != null) {
                            resultado += "  Operador Relacional -->     " + t + "                                               (" + evaluarOperadorRelacional(String.valueOf(t)) + ")\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                        }
                        if (evaluarDelimitador(String.valueOf(t)) != null) {
                            resultado += "  Delimitador -->     " + t + "                                               (" + evaluarDelimitador(String.valueOf(t)) + ")\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                            varPalabReserv = "";
                            varTipoDato = "";
                        }
                        if (evaluarOperadorAritmetico(String.valueOf(t)) != null) {
                            resultado += "  Operador Aritmético -->     " + t + "                                               (" + evaluarOperadorAritmetico(String.valueOf(t)) + ")\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                        }
                        i++;
                    } else {
                        do {
                            switch (estado) {
                                case 0:
                                    if (Character.isDigit(t)) {
                                        cod_entrada = 0;
                                        estado = misEstados[estado][cod_entrada]; //== 1
                                        concat += t;
                                        i++;
                                    } else if ((int) t == 46) {
                                        cod_entrada = 1;
                                        estado = misEstados[estado][cod_entrada]; //== -4
                                        concat = cad;
                                        i = longitud_cad;
                                    } else if (Character.isLetter(t)) {
                                        cod_entrada = 2;
                                        estado = misEstados[estado][cod_entrada]; //== 4
                                        concat += t;
                                        i++;
                                    } else {
                                        cod_entrada = 3;
                                        estado = misEstados[estado][cod_entrada]; //== -4
                                        concat = cad;
                                        i = longitud_cad;
                                    }
                                    break;
                                case 1:
                                    if (Character.isDigit(t)) {
                                        cod_entrada = 0;
                                        estado = misEstados[estado][cod_entrada]; //== 1
                                        concat += t;
                                        i++;
                                    } else if ((int) t == 46) {
                                        cod_entrada = 1;
                                        estado = misEstados[estado][cod_entrada]; //== 2
                                        concat += t;
                                        i++;
                                    } else if (Character.isLetter(t)) {
                                        cod_entrada = 2;
                                        estado = misEstados[estado][cod_entrada]; //== -1
                                        concat = cad;
                                        i = longitud_cad;
                                    } else {
                                        cod_entrada = 3;
                                        estado = misEstados[estado][cod_entrada]; //== -1
                                        concat = cad;
                                        i = longitud_cad;
                                    }
                                    break;
                                case 2:
                                    if (Character.isDigit(t)) {
                                        cod_entrada = 0;
                                        estado = misEstados[estado][cod_entrada]; //== 3
                                        concat += t;
                                        i++;
                                    } else if ((int) t == 46) {
                                        cod_entrada = 1;
                                        estado = misEstados[estado][cod_entrada]; //== -2
                                        concat = cad;
                                        i = longitud_cad;
                                    } else if (Character.isLetter(t)) {
                                        cod_entrada = 2;
                                        estado = misEstados[estado][cod_entrada]; //== -2
                                        concat = cad;
                                        i = longitud_cad;
                                    } else {
                                        cod_entrada = 3;
                                        estado = misEstados[estado][cod_entrada]; //== -2
                                        concat = cad;
                                        i = longitud_cad;
                                    }
                                    break;
                                case 3:
                                    if (Character.isDigit(t)) {
                                        cod_entrada = 0;
                                        estado = misEstados[estado][cod_entrada]; //== 3
                                        concat += t;
                                        i++;
                                    } else if ((int) t == 46) {
                                        cod_entrada = 1;
                                        estado = misEstados[estado][cod_entrada]; //== -2
                                        concat = cad;
                                        i = longitud_cad;
                                    } else if (Character.isLetter(t)) {
                                        cod_entrada = 2;
                                        estado = misEstados[estado][cod_entrada]; //== -2
                                        concat = cad;
                                        i = longitud_cad;
                                    } else {
                                        cod_entrada = 3;
                                        estado = misEstados[estado][cod_entrada]; //== -2
                                        concat = cad;
                                        i = longitud_cad;
                                    }
                                    break;
                                case 4:
                                    if (Character.isDigit(t)) {
                                        cod_entrada = 0;
                                        estado = misEstados[estado][cod_entrada]; //== 4
                                        concat += t;
                                        i++;
                                    } else if ((int) cad.charAt(i) == 46) {
                                        cod_entrada = 1;
                                        estado = misEstados[estado][cod_entrada]; //== -3
                                        concat = cad;
                                        i = longitud_cad;
                                    } else if (Character.isLetter(t)) {
                                        cod_entrada = 2;
                                        estado = misEstados[estado][cod_entrada]; //== 4
                                        concat += t;
                                        i++;
                                    } else {
                                        cod_entrada = 3;
                                        estado = misEstados[estado][cod_entrada]; //== -3
                                        concat = cad;
                                        i = longitud_cad;
                                    }
                                    break;
                            }
                            if (i != longitud_cad) {
                                t = cad.charAt(i);
                            }
                        } while (evaluarOperadorRelacional(String.valueOf(t)) == null && evaluarDelimitador(String.valueOf(t)) == null && evaluarOperadorAritmetico(String.valueOf(t)) == null && t != ' ' && i < longitud_cad);

                        if (estado == 1) {
                            resultado += "  Número -->     " + concat + "\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                        } else if (estado == 3) {
                            resultado += "  Decimal -->     " + concat + "\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                        } else if (estado == -1) {
                            resultado += "  Error Numérico -->     " + concat + "\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                        } else if (estado == -2) {
                            resultado += "  Error Decimal -->     " + concat + "\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                        } else if (estado == 4) {
                            if (palabraReservada(concat.toUpperCase()) != null) {
                                resultado += "  Palabra Reservada -->     " + concat.toUpperCase() + "                                               (" + palabraReservada(concat.toUpperCase()) + ")\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                                if (concat.toUpperCase().equalsIgnoreCase("CREAR")) {
                                    varPalabReserv = "CREAR";
                                    contadortipodato = 0;
                                } else if (varPalabReserv.equalsIgnoreCase("CREAR")) {
                                    if (tipoDato(concat.toUpperCase()) != null && contadortipodato == 0) {
                                        varTipoDato = concat.toUpperCase();
                                        contadortipodato += 1;
                                    } else {
                                        if (contadortipodato == 1) {
                                            mensajeSintactico += "\nError Sintáctico de duplicidad de tipo de datos";
                                        }
                                        contadortipodato += 1;
                                        varTipoDato = null;
                                    }
                                }
                            } else {
                                resultado += "  Identificador -->     " + concat + "\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";

                                if (varPalabReserv.equalsIgnoreCase("CREAR") && varTipoDato != null) {
                                    varNombreVar = concat;
                                    if (verificarExistenciaVar(varNombreVar, varTipoDato) == false) {
                                        ingresar(varNombreVar, varTipoDato);
                                        mensajeSintactico += "\nLa variable -->" + varNombreVar + "<-- DECLARADO CON ÉXITO";
                                        varPalabReserv = "";
                                        varTipoDato = "";
                                    } else {
                                        mensajeSintactico += "\nLa variable -->" + varNombreVar + "<-- YA SE ENCUENTRA DECLARADA";
                                    }
                                } else if (verificarExistenciaVar(concat, varTipoDato) == false) {
                                    mensajeSintactico += "\nLa variable -->" + concat + "<-- NO HA SIDO DECLARADO";
                                    varPalabReserv = "";
                                    varTipoDato = "";
                                } 
//                                else {
//                                    varPalabReserv = "";
//                                    varTipoDato = "";
//                                }
                            }




                        } else if (estado == -3) {
                            resultado += "  Error Identificador -->     " + concat + "\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                        } else if (estado == -4) {
                            resultado += "  NO DECLARADO -->     " + concat + "\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                        } else if (estado == 2) {
                            resultado += "  Error Numérico -->     " + concat + "\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                        } else {
                            resultado += "  NO DECLARADO -->     " + concat + "\n------------------------------------------------------------------------------------------------------------------------------------------------------------\n";
                        }
                        concat = "";
                        estado = 0;
                    }
                }
            }//end while espacio
        }//end while linea
    }

    /**
     * Método que evalua la existencia de nuestro caracter
     */
    public static String evaluarOperadorRelacional(String cad) {
        Hashtable RESERVADA = new Hashtable();
        RESERVADA.put("<", "Signo menor");
        RESERVADA.put(">", "Signo mayor");
        RESERVADA.put("=", "Signo igual");
        RESERVADA.put("&", "Asignación");
        RESERVADA.put("!", "Menor o igual");
        RESERVADA.put("¡", "Mayor o igual");
        RESERVADA.put("#", "Secuencia lógica Y");
        RESERVADA.put("°", "Secuencia lógica O");

        String Descripcion = null;
        if (RESERVADA.get(cad) == null) {
            Descripcion = null;
        } else {
            Descripcion = String.valueOf(RESERVADA.get(cad));
        }
        return Descripcion;
    }

    public static String evaluarDelimitador(String cad) {
        Hashtable RESERVADA = new Hashtable();
        RESERVADA.put(",", "Separador de parámetros");
        RESERVADA.put(";", "Símbolo terminal de línea");
        RESERVADA.put("[", "Inicial");
        RESERVADA.put("]", "Final");
        RESERVADA.put("(", "Paréntesis, apertura de parámetro inicial");
        RESERVADA.put(")", "Paréntesis, apertura de parámetro final");
        RESERVADA.put("\"", "Comillas");
        RESERVADA.put("$", "Símbolo de comentario");

        String Descripcion = null;
        if (RESERVADA.get(cad) == null) {
            Descripcion = null;
        } else {
            Descripcion = String.valueOf(RESERVADA.get(cad));
        }
        return Descripcion;
    }

    public static String evaluarOperadorAritmetico(String cad) {
        Hashtable OPERADOR_ARITMETICO = new Hashtable();
        OPERADOR_ARITMETICO.put("+", "Símbolo de adición");
        OPERADOR_ARITMETICO.put("-", "Símbolo de resta");
        OPERADOR_ARITMETICO.put("*", "Símbolo de multiplicación");
        OPERADOR_ARITMETICO.put("/", "Símbolo de división");

        String Descripcion = null;
        if (OPERADOR_ARITMETICO.get(cad) == null) {
            Descripcion = null;
        } else {
            Descripcion = String.valueOf(OPERADOR_ARITMETICO.get(cad));
        }
        return Descripcion;
    }

    public static String palabraReservada(String cad) {
        Hashtable RESERVADA = new Hashtable();
        RESERVADA.put("FUNCION", "Palabra reservada para tipo de método");
        RESERVADA.put("PROCEDIMIENTO", "Palabra reservada para tipo de método");
        RESERVADA.put("SI", "Palabra reservada para sentencia SI");
        RESERVADA.put("ENTONCES", "Palabra reservada para sentencia SI");
        RESERVADA.put("SINOSI", "Palabra reservada para sentencia SI");
        RESERVADA.put("FINSI", "Palabra reservada para sentencia SI");
        RESERVADA.put("MIENTRAS", "Palabra reservada para sentencia MIENTRAS");
        RESERVADA.put("LEER", "Palabra reservada para leer un dato de entrada");
        RESERVADA.put("ESCRIBIR", "Palabra reservada para imprimir una cadena ");
        RESERVADA.put("CREAR", "Palabra reservada para crear una variable");
        RESERVADA.put("CREARTE", "Palabra reservada para crear arrays");
        RESERVADA.put("LONGITUD", "Palabra reservada para medir tamaño de cadena");
        RESERVADA.put("EXTRAER", "Palabra reservada para poder extraer un pedazo de cadena");
        RESERVADA.put("ASCII", "Palabra reservada para convertir carácter a un número ASCII");
        RESERVADA.put("CONCAT", "Palabra reservada para concatenar cadenas");
        RESERVADA.put("TAMA", "Palabra reservada para tamaño fuente");
        RESERVADA.put("REDON", "Palabra reservada para redondeo de decimales");
        RESERVADA.put("POTEN", "Palabra reservada para obtener potencia");
        RESERVADA.put("MODUL", "Palabra reservada para obtener módulo");
        RESERVADA.put("VERDADERO", "Palabra reservada para booleanos");
        RESERVADA.put("FALSO", "Palabra reservada para booleanos");
        RESERVADA.put("BINICIO", "Palabra reservada para pieza representativa del comienzo del fichero");
        RESERVADA.put("BFIN", "Palabra reservada para pieza representativa del final del fichero");
        RESERVADA.put("BYTE", "Palabra reservada para datos enteros");
        RESERVADA.put("CORTO", "Palabra reservada para datos enteros");
        RESERVADA.put("ENTERO", "Palabra reservada para datos enteros");
        RESERVADA.put("LARGO", "Palabra reservada para datos enteros");
        RESERVADA.put("DECIMAL", "Palabra reservada para datos flotantes");
        RESERVADA.put("REAL", "Palabra reservada para datos flotantes");
        RESERVADA.put("CARACTER", "Palabra reservada para otros tipos de datos");
        RESERVADA.put("BOOLEANO", "Palabra reservada para otros tipos de datos");
        RESERVADA.put("PARA", "Palabra reservada para sentencia PARA");
        RESERVADA.put("HASTA", "Palabra reservada para sentencia PARA");
        RESERVADA.put("FINPARA", "Palabra reservada para sentencia PARA");
        RESERVADA.put("PRIVADO", "Palabras reservada de métodos de acceso");
        RESERVADA.put("PUBLICO", "Palabras reservada de métodos de acceso");
        RESERVADA.put("AMISTOSO", "Palabras reservada de métodos de acceso");
        RESERVADA.put("PROTEGIDO", "Palabras reservada de métodos de acceso");
        RESERVADA.put("NULO", "Palabras reservada que indica valor vacío");

        String Descripcion = null;
        if (RESERVADA.get(cad) == null) {
            Descripcion = null;
        } else {
            Descripcion = String.valueOf(RESERVADA.get(cad));
        }
        return Descripcion;
    }

    public static String tipoDato(String cad) {
        Hashtable DATO = new Hashtable();
        DATO.put("BYTE", "Palabra reservada para tipo de dato byte");
        DATO.put("CORTO", "Palabra reservada para tipo de dato corto");
        DATO.put("ENTERO", "Palabra reservada para tipo de dato entero");
        DATO.put("LARGO", "Palabra reservada para tipo de dato largo");
        DATO.put("DECIMAL", "Palabra reservada para tipo de dato decimal");
        DATO.put("REAL", "Palabra reservada para tipo de dato real");
        DATO.put("CARACTER", "Palabra reservada para tipo de dato caracter");
        DATO.put("BOOLEANO", "Palabra reservada para tipo de dato booleano");

        String Descripcion = null;
        if (DATO.get(cad) == null) {
            Descripcion = null;
        } else {
            Descripcion = String.valueOf(DATO.get(cad));
        }
        return Descripcion;
    }

    public void ingresar(String nombreVariable, String tipoDatoVar) {
        int numeroFila = 0;
        for (int i = 0; i < 1000; i++) {
            for (int j = 0; j < 2; j++) {
                if (array[i][0] == null) {
                    numeroFila = i;

                    i = 1000;
                    j = 5;
                }

            }
        }

        array[numeroFila][0] = nombreVariable;
        array[numeroFila][1] = tipoDatoVar;
    }

    public boolean verificarExistenciaVar(String nombreVariable, String tipoDatoVar) {
        boolean rpta = false;
        for (int i = 0; i < array.length; i++) {

            if (nombreVariable.equals(array[i][0])) {

                rpta = true;
                i = array.length + 1;
            }

        }
        return rpta;
    }
}